﻿using MediatR;
using SmartCity.ProcessEngine.Api.Write.Application.Command.EventHandling;
using SmartCity.ProcessEngine.Domain.Entities;
using SmartCity.ProcessEngine.ErrorCode;
using SmartCity.ProcessEngine.Infrastructure.Interface;
using System.Transactions;
using Yitter.IdGenerator;

namespace SmartCity.ProcessEngine.Api.Write.Application.CommandHandler.EventHandling
{
    /// <summary>
    /// 执行实例节点的审批工作的处理类
    /// </summary>
    public class ExeInstanceNodeHandler : IRequestHandler<ExeInstanceNodeCommand, ApiResult<int>>
    {
        private readonly IBaseRepository<InstanceModel> insRepo;
        private readonly IBaseRepository<InstanceRecardModel> recarRepo;
        private readonly IBaseRepository<FormNodeConfigModel> cfgNodeRepo;
        private readonly IBaseRepository<NodeModel> nodeRepo;
        private readonly ILogger<ExeInstanceNodeHandler> logger;

        /// <summary>
        /// 注入审批流程实例所需的资源,包括实例仓储,审批记录仓储,日志组件对象,节点配置仓储,节点仓储
        /// </summary>
       
        public ExeInstanceNodeHandler(IBaseRepository<InstanceModel> insRepo,
            IBaseRepository<InstanceRecardModel> recarRepo,
            IBaseRepository<FormNodeConfigModel> cfgNodeRepo,
            IBaseRepository<NodeModel> nodeRepo,
            ILogger<ExeInstanceNodeHandler> logger)
        {
            this.insRepo = insRepo;
            this.recarRepo = recarRepo;
            this.cfgNodeRepo = cfgNodeRepo;
            this.nodeRepo = nodeRepo;
            this.logger = logger;
        }

        /// <summary>
        /// 审批流程处理方法
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ApiResult<int>> Handle(ExeInstanceNodeCommand request, CancellationToken cancellationToken)
        {
            //根据实例id,找到实例实体对象
            var instance = await insRepo.GetModel(request.InstanceId);
            if (instance == null) {
                return new ApiResult<int>().Fail("您要审批的流程实例不存在!");
            }
            //判断当前登录人是否有权限审批  //IsAgree
            if (instance.NextOperatorName != request.AccountName) {
                return new ApiResult<int>().Fail("您无权审核该流程!");
            }

            //重置当前节点
            instance.CurrentNodeName = instance.NextNodeName; //把下一个节点名字赋值给当前节点
            instance.CurrentNodeId = instance.NextNodeId??0;
            instance.CurrentOperatorName = request.AccountName;
            instance.UpdateTime = DateTime.Now;
            //查找下一个节点 ...
            var nextCfgNode = cfgNodeRepo.GetAll().OrderBy(x=>x.Id).Where(x=>!x.IsDeleted&&x.Id> instance.CurrentNodeId&&x.FormId==instance.FormId).FirstOrDefault();
            if (nextCfgNode == null)//如果没有下一个节点配置了,把实例的下一节点都清空
            {
                instance.NextNodeId = null;
                instance.NextNodeName = "";
                instance.NextOperatorName = "";                                                               
            
            }
            else {

                instance.NextNodeId = nextCfgNode.Id;
                var nextNode =await nodeRepo.GetModel(nextCfgNode.CurrentNodeId);//根据配置里的节点id,查找节点实例
                instance.NextNodeName = nextNode?.NodeName;//节点名称
                instance.NextOperatorName = nextCfgNode.AccountName;//下一个节点操作人
            }


            //实例(你要处理的这个实例)审核记录(相当于日志)是新数据(新增一条),需要实例化(技术用语)记录类(相当于日志的审核记录类)
            InstanceRecardModel instanceRecard = new InstanceRecardModel();
            instanceRecard.Id = YitIdHelper.NextId();
            instanceRecard.IntanceId = request.InstanceId;//所属流程实例
            instanceRecard.NodeId = instance.CurrentNodeId;
            instanceRecard.NodeName = instance.CurrentNodeName;
            instanceRecard.OperatorName = instance.CurrentOperatorName;
            instanceRecard.OperatorOpinion = request.OperatorOpinion;//审批意见
            instanceRecard.ApproveStatus = request.IsAgree ? ApproveStatus.通过 : ApproveStatus.不通过;

            instanceRecard.CreatedTime= DateTime.Now;

            if (request.IsAgree == false)//不同意,流程直接结束
            {
                instance.FlowStatus = InstanceStatus.完成;
            }
            else { //同意,你还需要判断是否有下一节点
                if (nextCfgNode != null)
                {
                    instance.FlowStatus = InstanceStatus.处理中;//把实例的状态设置为完成  
                }
                else {
                    instance.FlowStatus = InstanceStatus.完成;
                }            
            }

            int r = 0;
            int r1 = 0;


            using (TransactionScope tran = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            {
                try
                {
                    r = await insRepo.UpdateAsync(instance);
                    r1 = await recarRepo.CreateAsync(instanceRecard);
                    tran.Complete();
                }
                catch (Exception e)
                {
                    logger.LogError("审批流程时发生异常,操作已经回滚");
                    throw;
                }
            }


            if (r > 0 && r1 > 0)
            {
                return new ApiResult<int>().Success("审批流程成功", r + r1);
            }
            else {
                return new ApiResult<int>().Fail("审批流程失败");
            }
        }
    }
}
